/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "S_Px车.h"

#include "../A_核心/Px物体形状创建.h"

using namespace physx;
using namespace std;





/*enum {
	COLLISION_FLAG_GROUND = 1 << 0,
	COLLISION_FLAG_WHEEL = 1 << 1,
	COLLISION_FLAG_CHASSIS = 1 << 2,
	COLLISION_FLAG_OBSTACLE = 1 << 3,
	COLLISION_FLAG_DRIVABLE_OBSTACLE = 1 << 4,
	碰撞FLAG_虚拟体 = 1 << 5,
	碰撞FLAG_静态物体 = 1 << 6,
	碰撞FLAG_地形 = 1 << 10,


	COLLISION_FLAG_GROUND_AGAINST = COLLISION_FLAG_CHASSIS | COLLISION_FLAG_OBSTACLE | COLLISION_FLAG_DRIVABLE_OBSTACLE,
	COLLISION_FLAG_WHEEL_AGAINST = COLLISION_FLAG_WHEEL | COLLISION_FLAG_CHASSIS | COLLISION_FLAG_OBSTACLE,
	COLLISION_FLAG_CHASSIS_AGAINST = COLLISION_FLAG_GROUND | COLLISION_FLAG_CHASSIS | COLLISION_FLAG_OBSTACLE | COLLISION_FLAG_DRIVABLE_OBSTACLE,
	COLLISION_FLAG_OBSTACLE_AGAINST = COLLISION_FLAG_GROUND | COLLISION_FLAG_WHEEL | COLLISION_FLAG_CHASSIS | COLLISION_FLAG_OBSTACLE | COLLISION_FLAG_DRIVABLE_OBSTACLE,
	COLLISION_FLAG_DRIVABLE_OBSTACLE_AGAINST = COLLISION_FLAG_GROUND | COLLISION_FLAG_CHASSIS | COLLISION_FLAG_OBSTACLE | COLLISION_FLAG_DRIVABLE_OBSTACLE,

	碰撞FLAG_静态虚拟体组 = 碰撞FLAG_虚拟体 | 碰撞FLAG_地形,

};*/









static PxVec3		g_射线[8] = {
	{ 0.0f,			0.0f,	1.0f },

	{ 0.70711f,		0.0f,	0.70711f },
	{ -0.70711f,	0.0f,	0.70711f },

	{ 1.0f,			0.0f,	0.0f },
	{ -1.0f,		0.0f,	0.0f },

	{ 0.0f,			0.0f,	-1.0f },
	{ 0.70711f,		0.0f,	-0.70711f },
	{ -0.70711f,	0.0f,	-0.70711f }
};


static float32							g车辆场景探测距离[8] = { 15, 15,15,15,15,15,15,15 };













//Drivable surface types.
/*enum {
	SURFACE_TYPE_TARMAC,
	MAX_NUM_SURFACE_TYPES
};*/
/*enum
{
	SURFACE_TYPE_MUD = 0,
	SURFACE_TYPE_TARMAC,
	SURFACE_TYPE_SNOW,
	SURFACE_TYPE_GRASS,
	MAX_NUM_SURFACE_TYPES
};*/


//Tire model friction for each combination of drivable surface type and tire type.
static PxF32 gTireFrictionMultipliers[MAX_NUM_SURFACE_TYPES][MAX_NUM_TIRE_TYPES] = {
	//NORMAL,	WORN
	{ 1.00f,		0.1f }//TARMAC
};



PxVehicleDrivableSurfaceToTireFrictionPairs* f_创建轮胎摩擦面(const PxMaterial* defaultMaterial)
{
	PxVehicleDrivableSurfaceType surfaceTypes[1];
	surfaceTypes[0].mType = SURFACE_TYPE_TARMAC;

	const PxMaterial* surfaceMaterials[1];
	surfaceMaterials[0] = defaultMaterial;

	PxVehicleDrivableSurfaceToTireFrictionPairs* surfaceTirePairs =
		PxVehicleDrivableSurfaceToTireFrictionPairs::allocate(MAX_NUM_TIRE_TYPES, MAX_NUM_SURFACE_TYPES);

	surfaceTirePairs->setup(MAX_NUM_TIRE_TYPES, MAX_NUM_SURFACE_TYPES, surfaceMaterials, surfaceTypes);

	for (PxU32 i = 0; i < MAX_NUM_SURFACE_TYPES; i++)
	{
		for (PxU32 j = 0; j < MAX_NUM_TIRE_TYPES; j++)
		{
			surfaceTirePairs->setTypePairFriction(i, j, gTireFrictionMultipliers[i][j]);
		}
	}
	return surfaceTirePairs;
}
















S_Px车轮::S_Px车轮(S_Px物理引擎核心* core, const S_车轮参数& 属性, S_物理几何体& geom, S_物理材质& 材质) {
	m_物理引擎枚举 = E_物理引擎::E_物理引擎_PhysX;
	m_属性 = 属性;
	//m_属性.m_车轮半径 = 半径;
	//m_属性.m_轮胎宽度 = 宽度;
	m_属性.m_惯性力矩 = 0.5 * m_属性.m_重量*m_属性.m_半径*m_属性.m_半径;
	m_车轮碰撞过滤 = PxFilterData(COLLISION_FLAG_WHEEL, COLLISION_FLAG_WHEEL_AGAINST, 0, 0);

	//m_车轮网格 = (PxConvexMeshGeometry*)geom.f_get几何体物理对象();
	vector<vec3> 车辆网格顶点(属性.m_精度*2);
	f_构建圆柱_v3(m_属性.m_轮胎宽度, m_属性.m_半径, 属性.m_精度, 车辆网格顶点.data());
	PxConvexMeshDesc 车辆网格描述;
	车辆网格描述.points.count = 属性.m_精度*2;
	车辆网格描述.points.stride = sizeof(vec3);
	车辆网格描述.points.data = 车辆网格顶点.data();
	车辆网格描述.flags = PxConvexFlag::eCOMPUTE_CONVEX;
	PxDefaultMemoryOutputStream buf;
	if (core->m_Cooking->cookConvexMesh(车辆网格描述, buf)) {
		PxDefaultMemoryInputData id(buf.getData(), buf.getSize());
		auto 网格 = core->m_Physics->createConvexMesh(id);

		m_车轮网格 = new PxConvexMeshGeometry(网格, PxMeshScale(PxVec3(1.0f)));
	}
	m_轮胎材质 = (PxMaterial*)材质.f_get物理材质数据();
	
	
}

S_Px车轮::~S_Px车轮() {

}



physx::PxVehicleWheelData S_Px车轮::f_get轮子模拟参数(const E_车轮ID id) {
	physx::PxVehicleWheelData wheels;

	wheels.mMass = m_属性.m_重量;
	wheels.mMOI = m_属性.m_惯性力矩;
	wheels.mRadius = m_属性.m_半径;
	wheels.mWidth = m_属性.m_轮胎宽度;

	switch (id) {
	case e_车轮_前左:
	case e_车轮_前右:
		//设置转向
		wheels.mMaxSteer = M_角度转弧度(m_属性.m_最大转向角度);
		break;

	case e_车轮_后左:
	case e_车轮_后右:
		//设置手刹
		wheels.mMaxHandBrakeTorque = m_属性.m_手刹强度;
		break;
	default:
		break;
	}

	return wheels;
}




























S_Px车::S_Px车(S_Px物理引擎核心* core, const S_车体参数& 车体参数) {
	m_物理引擎枚举 = E_物理引擎::E_物理引擎_PhysX;
	m_Type = E_物理体类型::E_物理体_车辆;

	
	m_车体参数 = 车体参数;
	m_车体刚体 = 0;
	mPlayerVehicle = 0;
	//return;

	m_车体碰撞过滤	= PxFilterData(COLLISION_FLAG_CHASSIS, COLLISION_FLAG_CHASSIS_AGAINST, 0, 0);
	m_轮胎模拟数据	= PxVehicleWheelsSimData::allocate(车体参数.m_车轮数量);
	m_车辆驱动		= PxVehicleDrive4W::allocate(车体参数.m_车轮数量);
	


	

	m_车体参数.m_底盘重量 = 1500;
	m_车体参数.m_底盘边界 = { 1.6f, 1.0f, 3.5f };
	m_车体参数.m_惯性力矩 = {
		(m_车体参数.m_底盘边界.y* m_车体参数.m_底盘边界.y + m_车体参数.m_底盘边界.z* m_车体参数.m_底盘边界.z)* m_车体参数.m_底盘重量 / 12.0f,
		(m_车体参数.m_底盘边界.x* m_车体参数.m_底盘边界.x + m_车体参数.m_底盘边界.z* m_车体参数.m_底盘边界.z)* m_车体参数.m_底盘重量 / 12.0f,
		(m_车体参数.m_底盘边界.x* m_车体参数.m_底盘边界.x + m_车体参数.m_底盘边界.y* m_车体参数.m_底盘边界.y)* m_车体参数.m_底盘重量 / 12.0f
	};
	m_车体参数.m_惯性力矩.y *= 0.8f;

	//m_车体参数.m_重心偏移 = { 0.0f, -m_车体参数.m_底盘边界.y*0.5f-0.5f, 0.5f };
	m_车体参数.m_重心偏移 = { 0.0f, 0.0f, 0.0f };
	m_车体参数.m_离合器强度 = 10.0;



	m_车体刚体 = core->m_Physics->createRigidDynamic(PxTransform(PxIdentity));
	//m_车体刚体 = (PxRigidDynamic*)(车体参数.m_车体刚体->f_getBody());
	//m_车体刚体 = dynamic_cast<PxRigidDynamic*>((PxRigidActor*)(a));
	m_车体刚体->setGlobalPose(PxTransform({ 0, 5, 0 }));


	m_车体刚体->setMass(m_车体参数.m_底盘重量);
	m_车体刚体->setMassSpaceInertiaTensor({ m_车体参数.m_惯性力矩.x, m_车体参数.m_惯性力矩.y, m_车体参数.m_惯性力矩.z });
	m_车体刚体->setCMassLocalPose(PxTransform({ m_车体参数.m_重心偏移.x,m_车体参数.m_重心偏移.y, m_车体参数.m_重心偏移.z }, PxQuat(PxIdentity)));
	//m_车体刚体->setLinearDamping(0.0);
	//m_车体刚体->setMassSpaceInertiaTensor({ 50,50,50 });
	//m_车体刚体->setAngularDamping(10.0);
	//m_车身材质 = core->m_Physics->createMaterial(0.0, 0.0, 0.0);
	m_VehicleInputData.setAnalogHandbrake(0.0);
	m_VehicleInputData.setAnalogBrake(0.0);
	m_VehicleInputData.setAnalogAccel(0.0f);
	m_VehicleInputData.setAnalogSteer(0.0f);
	//m_VehicleInputData.setGearUp(1.0f);
	//m_VehicleInputData.setGearDown(1.0f);
	m_VehicleInputData.setDigitalAccel(false);
	m_VehicleInputData.setDigitalSteerLeft(false);
	m_VehicleInputData.setDigitalSteerRight(false);
	m_VehicleInputData.setDigitalBrake(false);
	m_VehicleInputData.setDigitalHandbrake(false);


	m_车辆碰撞车辆图形 = new PxSphereGeometry(10);






#if PX_DEBUG_VEHICLE_ON
	mDebugRenderActiveGraphChannelWheel = 0;
	mDebugRenderActiveGraphChannelEngine = 0;
	mTelemetryData4W = NULL;
	mTelemetryData6W = NULL;
#endif



#if PX_DEBUG_VEHICLE_ON

	mDebugRenderActiveGraphChannelWheel = PxVehicleWheelGraphChannel::eWHEEL_OMEGA;
	mDebugRenderActiveGraphChannelEngine = PxVehicleDriveGraphChannel::eENGINE_REVS;

	{
		const PxF32 graphSizeX = 0.25f;
		const PxF32 graphSizeY = 0.25f;
		const PxF32 engineGraphPosX = 0.5f;
		const PxF32 engineGraphPosY = 0.5f;
		const PxF32 wheelGraphPosX[4] = { 0.75f,0.25f,0.75f,0.25f };
		const PxF32 wheelGraphPosY[4] = { 0.75f,0.75f,0.25f,0.25f };
		const PxVec3 backgroundColor(255, 255, 255);
		const PxVec3 lineColorHigh(255, 0, 0);
		const PxVec3 lineColorLow(0, 0, 0);

		mTelemetryData4W = PxVehicleTelemetryData::allocate(4);

		mTelemetryData4W->setup
		(graphSizeX, graphSizeY,
			engineGraphPosX, engineGraphPosY,
			wheelGraphPosX, wheelGraphPosY,
			backgroundColor, lineColorHigh, lineColorLow);
	}

	{
		const PxF32 graphSizeX = 0.225f;
		const PxF32 graphSizeY = 0.225f;
		const PxF32 engineGraphPosX = 0.5f;
		const PxF32 engineGraphPosY = 0.5f;
		const PxF32 wheelGraphPosX[6] = { 0.75f,0.25f,0.75f,0.25f,0.75f,0.25f };
		const PxF32 wheelGraphPosY[8] = { 0.83f,0.83f,0.17f,0.17f,0.5f,0.5f };
		const PxVec3 backgroundColor(255, 255, 255);
		const PxVec3 lineColorHigh(255, 0, 0);
		const PxVec3 lineColorLow(0, 0, 0);

		mTelemetryData6W = PxVehicleTelemetryData::allocate(6);

		mTelemetryData6W->setup
		(graphSizeX, graphSizeY,
			engineGraphPosX, engineGraphPosY,
			wheelGraphPosX, wheelGraphPosY,
			backgroundColor, lineColorHigh, lineColorLow);
	}

#endif

	

	f_add构建车体(车体参数.m_车轮, 车体参数.m_车轮数量);

	m_车辆驱动->setup(core->m_Physics, m_车体刚体, *m_轮胎模拟数据, f_get驱动参数(), 0);


	auto m_Gem = PxBoxGeometry(0.8, 0.1, 1.5);
	m_车体形状.resize(1);
	m_车体形状[0] = PxRigidActorExt::createExclusiveShape(*m_车体刚体, m_Gem, *(PxMaterial*)(车体参数.m_车体材质[0]->f_get物理材质数据()));
}

S_Px车::~S_Px车() {
	m_车辆驱动->free();
}



void S_Px车::f_add构建车体(S_车轮参数* 车轮s, uint8 车轮数量) {
	//PxConvexMesh* 车体网格 = f_Px_创建凸包碰撞网格(core->m_Physics, core->m_Cooking, mesh);
	//m_车身材质 = (PxMaterial*)材质.f_get物理材质数据();
	PxFilterData chassisQryFilterData;
	chassisQryFilterData.word3 = UNDRIVABLE_SURFACE;

	

	m_轮胎模拟数据->setSubStepCount(5.0f, 3, 1);
	m_轮胎模拟数据->setMinLongSlipDenominator(4.0f);

	vector< physx::PxVec3> 车轮位置;
	for (uint32 i = 0; i < 车轮数量; ++i) {
		车轮位置.push_back({ 车轮s[i].m_位置.x, 车轮s[i].m_位置.y, 车轮s[i].m_位置.z });
	}
	m_悬挂质量.resize(8);
	//physx::PxVec3 location = { 车轮.m_位置.x, 车轮.m_位置.y, 车轮.m_位置.z };
	PxVehicleComputeSprungMasses(车轮位置.size(), 车轮位置.data(), { m_车体参数.m_重心偏移.x, m_车体参数.m_重心偏移.y, m_车体参数.m_重心偏移.z }, m_车体参数.m_底盘重量, 1, m_悬挂质量.data());


	for (uint32 i = 0; i < 车轮数量; ++i) {
		f_add构建车轮(车轮s[i]);
	}



	

	/*for (uint32 i = 0; i < 车体数量; ++i) {
		auto& geom = *几何体[i];
		PxGeometry* mesh = (PxGeometry*)geom.f_get几何体物理对象();

		//auto m_Geom = new PxConvexMeshGeometry(mesh, PxMeshScale(PxVec3(1.0, 1.0, 1.0)) );
		auto m_Gem = PxBoxGeometry(0.8, 0.5, 1.5);
		PxShape* chassisShape = PxRigidActorExt::createExclusiveShape(*m_车体刚体, m_Gem, *(PxMaterial*)材质[i]->f_get物理材质数据());

		chassisShape->setQueryFilterData(chassisQryFilterData);
		chassisShape->setSimulationFilterData(m_车体碰撞过滤);
		chassisShape->setLocalPose(PxTransform(PxIdentity));

		chassisShape->setContactOffset(0.02);
		chassisShape->setRestOffset(-0.001);

		//m_车体网格.push_back(车体网格);
		m_车体形状.push_back(chassisShape);
	}*/

}

void S_Px车::f_add构建车轮(S_车轮参数& 车轮) {
	//m_车轮 = 车轮s;
	//uint32 num = 车轮s.size();
	//m_车轮.push_back(&车轮);
	
	//for (auto& 车轮 : 车轮s) {
	PxFilterData wheelQryFilterData;
	wheelQryFilterData.word3 = UNDRIVABLE_SURFACE;
	
	auto* 车轮物理体 = dynamic_cast<S_Px车轮*>(车轮.m_车轮物理体);
	auto* 车轮形状 = PxRigidActorExt::createExclusiveShape(*m_车体刚体, *(车轮物理体->m_车轮网格), *(车轮物理体->m_轮胎材质));
	车轮形状->setQueryFilterData(wheelQryFilterData);
	车轮形状->setSimulationFilterData(车轮物理体->m_车轮碰撞过滤);
	PxTransform startTransform(PxVec3(车轮.m_位置.x, 车轮.m_位置.y, 车轮.m_位置.z), PxQuat(PxIdentity));
	车轮形状->setLocalPose(startTransform);
	//new车轮.m_中心偏移 = 中心偏移;
	m_车轮形状.push_back(车轮形状);


	PxVehicleWheelData 车轮参数 = 车轮物理体->f_get轮子模拟参数(车轮.m_安放方位);



	PxVehicleTireData tires;
	tires.mType = TIRE_TYPE_WETS;
	//PxVehicleTireData tires[4];
	//tires[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].mType = TIRE_TYPE_SLICKS;
	//tires[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT].mType = TIRE_TYPE_SLICKS;
	//tires[PxVehicleDrive4WWheelOrder::eREAR_LEFT].mType = TIRE_TYPE_WETS;
	//tires[PxVehicleDrive4WWheelOrder::eREAR_RIGHT].mType = TIRE_TYPE_WETS;



	PxVec3 悬挂压缩方向 = { 车轮.m_悬挂压缩方向.x, 车轮.m_悬挂压缩方向.y, 车轮.m_悬挂压缩方向.z };
	//vec3 车轮中心偏移 = vec_sub(车轮.m_位置, m_车体属性.m_重心偏移);
	vec3 车轮中心偏移 = 车轮.m_位置;

	vec3 悬挂施加力偏移 = { 车轮中心偏移.x, -1.3, 车轮中心偏移.z };
	//vec_normalize(&悬挂施加力偏移);
	vec3 轮胎施加点 = { 车轮中心偏移.x , -1.3, 车轮中心偏移.z };





	//设置悬挂
	PxVehicleSuspensionData 悬挂;
	//计算每个悬挂弹簧支撑的质量。
	

	悬挂.mMaxCompression = 0.3f;				//压缩比
	悬挂.mMaxDroop = 0.3f;						//下垂比
	悬挂.mSpringStrength = 300.0f;				//弹簧强度
	悬挂.mSpringDamperRate = 400.0f;			//弹簧阻尼率
	//悬挂.mSprungMass = m_车体属性.m_底盘重量 / 4;			//簧载质量
	悬挂.mSprungMass = m_悬挂质量[车轮.m_安放方位];			//簧载质量

	//设置外倾角
	PxF32 静止状态外倾角 = 0.0;
	PxF32 最大下垂外倾角 = 0.03f;
	PxF32 最大压缩外倾角 = -0.03f;


	if (车轮.m_安放方位 & 1) {
		静止状态外倾角 *= -1.0;
		最大下垂外倾角 *= -1.0;
		最大压缩外倾角 *= -1.0;
	}

	悬挂.mCamberAtRest = 静止状态外倾角;
	悬挂.mCamberAtMaxDroop = 最大下垂外倾角;
	悬挂.mCamberAtMaxCompression = 最大压缩外倾角;


		
	

	
	

	PxFilterData qryFilterData;
	qryFilterData.word3 = UNDRIVABLE_SURFACE;

	m_轮胎模拟数据->setWheelData(车轮.m_安放方位, 车轮参数);
	m_轮胎模拟数据->setTireData(车轮.m_安放方位, tires);
	m_轮胎模拟数据->setSuspensionData(车轮.m_安放方位, 悬挂);
	m_轮胎模拟数据->setSuspTravelDirection(车轮.m_安放方位, 悬挂压缩方向);
	m_轮胎模拟数据->setWheelCentreOffset(车轮.m_安放方位, { 车轮中心偏移.x, 车轮中心偏移.y, 车轮中心偏移.z });
	m_轮胎模拟数据->setSuspForceAppPointOffset(车轮.m_安放方位, { 悬挂施加力偏移.x, 悬挂施加力偏移.y, 悬挂施加力偏移.z });
	m_轮胎模拟数据->setTireForceAppPointOffset(车轮.m_安放方位, { 轮胎施加点.x, 轮胎施加点.y, 轮胎施加点.z });
	//m_轮胎模拟数据->setSceneQueryFilterData(车轮.m_安放方位, qryFilterData);
	//m_轮胎模拟数据->setWheelShapeMapping(车轮.m_安放方位, PxI32(车轮.m_安放方位));
	

}

void S_Px车::f_add防撞杠(const E_车轮ID id, float32 刚性){
	return;

	PxVehicleAntiRollBarData 防撞杠;
	switch (id)
	{
	case e_车轮_前左:
	case e_车轮_前右:
		防撞杠.mWheel0 = PxVehicleDrive4WWheelOrder::eFRONT_LEFT;
		防撞杠.mWheel1 = PxVehicleDrive4WWheelOrder::eFRONT_RIGHT;
		break;

	case e_车轮_后左:
	case e_车轮_后右:
		防撞杠.mWheel0 = PxVehicleDrive4WWheelOrder::eREAR_LEFT;
		防撞杠.mWheel1 = PxVehicleDrive4WWheelOrder::eREAR_RIGHT;
		break;
	default:
		break;
	}

	防撞杠.mStiffness = 刚性;
	m_轮胎模拟数据->addAntiRollBarData(防撞杠);
}

physx::PxVehicleDriveSimData4W S_Px车::f_get驱动参数() {
	PxVehicleDriveSimData4W driveSimData;


	PxVehicleDifferential4WData 差速器;
	差速器.mType = PxVehicleDifferential4WData::eDIFF_TYPE_LS_4WD;
	driveSimData.setDiffData(差速器);

	PxVehicleEngineData engine;
	engine.mPeakTorque = m_车体参数.m_引擎_最大扭矩;
	engine.mMaxOmega = m_车体参数.m_引擎_最大转速;
	driveSimData.setEngineData(engine);

	PxVehicleGearsData 变速;
	变速.mSwitchTime = m_车体参数.m_变速_换挡时间;
	driveSimData.setGearsData(变速);

	PxVehicleClutchData 离合器;
	离合器.mStrength = m_车体参数.m_离合器强度;
	driveSimData.setClutchData(离合器);
	auto a = m_轮胎模拟数据->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_RIGHT).x;
	auto b = m_轮胎模拟数据->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_LEFT).x;
	PxVehicleAckermannGeometryData ackermann;
	ackermann.mAccuracy = 1.0f;
	ackermann.mAxleSeparation =
		fabs(m_轮胎模拟数据->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_LEFT).z - m_轮胎模拟数据->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_LEFT).z);
		
	ackermann.mFrontWidth =
		fabs(m_轮胎模拟数据->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_LEFT).x - m_轮胎模拟数据->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_RIGHT).x);
	
	ackermann.mRearWidth =
		fabs(m_轮胎模拟数据->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_LEFT).x - m_轮胎模拟数据->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_RIGHT).x);
		
	driveSimData.setAckermannGeometryData(ackermann);

	//cout << "lt ---- " << m_轮胎模拟参数->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_LEFT).x << " " << m_轮胎模拟参数->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_LEFT).x << endl;
	return driveSimData;
}




bool S_Px车::f_检测物体碰撞(physx::PxRigidActor* actor) {
	//return true;

	const PxMat44 shapePose(PxShapeExt::getGlobalPose(*m_车体形状[0], *m_车体刚体));
	
	PxVec3 原点 = shapePose.transform(PxVec3(0, 0, 0));

	//S_拾取结果 拾取结果[2];
	PxRaycastHit hit[2];
	PxHitFlags hitFlags = PxHitFlag::ePOSITION | PxHitFlag::eNORMAL | PxHitFlag::eDISTANCE;
	//PxRigidActor* Actor = dynamic_cast<PxRigidActor*>((PxRigidActor*)被碰撞对象.m_物理体);

	PxGeometry& 场景网格 = ((PxShape*)actor)->getGeometry().any();
	PxGeometry& 车辆网格 = m_车体形状[0]->getGeometry().any();



	m_碰撞次数 = 0;
	uint8 是否碰撞 = 0;
#pragma loop(vector_on)  
	for (uint8 i = 0; i < 8; ++i) {
		m_碰撞距离[i] = 0;

		m_探测射线[i] = shapePose.transform(g_射线[i]) - 原点;
		m_探测射线[i].normalize();
		uint8 isPenetrating = PxGeometryQuery::raycast(原点, m_探测射线[i], 场景网格, actor->getGlobalPose(), g车辆场景探测距离[i], hitFlags, 1, hit);
		是否碰撞 |= isPenetrating;
		if (isPenetrating) {
			m_碰撞距离[i] = DEF_Max(g车辆场景探测距离[i] - hit[0].distance, m_碰撞距离[i]);
		}
	}

	if (是否碰撞) {
		for (uint8 i = 0; i < 8; ++i) {
			if (m_碰撞距离[i] > 45) {
				bool isPenetrating = PxGeometryQuery::overlap(车辆网格, m_车体刚体->getGlobalPose(), 场景网格, actor->getGlobalPose());
				if (isPenetrating) {
					m_碰撞次数 += 1;
				}
			}
		}
	}


	return false;
}


vec3 S_Px车::f_get横向和前进速度()
{
	vec3 speed;

	speed.x = m_车辆驱动->computeSidewaysSpeed();
	speed.y = 0.0;
	speed.z = m_车辆驱动->computeForwardSpeed();

	return speed;
}








void S_Px车::f_加速(const float32 s) {
	m_车辆驱动->mDriveDynData.forceGearChange(PxVehicleGearsData::eFIRST);
	m_VehicleInputData.setAnalogAccel(s);
}

void S_Px车::f_倒车(const float32 s) {
	m_车辆驱动->mDriveDynData.forceGearChange(PxVehicleGearsData::eREVERSE);
	m_VehicleInputData.setAnalogAccel(s);
}

void S_Px车::f_刹车(const float32 s) {
	m_VehicleInputData.setAnalogBrake(s);
}

void S_Px车::f_手刹(const float32 s) {
	m_VehicleInputData.setAnalogHandbrake(s);
}

void S_Px车::f_转向(const float32 s){
	m_VehicleInputData.setAnalogSteer(s);
}

void S_Px车::f_加速(const bool c) {
	//m_车辆驱动->mDriveDynData.forceGearChange(PxVehicleGearsData::eFIRST);
	m_VehicleInputData.setDigitalAccel(c);
}

void S_Px车::f_倒车(const bool c) {
	if (c) {
		m_车辆驱动->mDriveDynData.forceGearChange(PxVehicleGearsData::eREVERSE);
	}
	else {
		m_车辆驱动->mDriveDynData.forceGearChange(PxVehicleGearsData::eFIRST);
	}

	m_VehicleInputData.setDigitalAccel(c);
}

void S_Px车::f_刹车(const bool c) {
	m_VehicleInputData.setDigitalBrake(c);
}

void S_Px车::f_手刹(const bool c) {
	m_VehicleInputData.setDigitalBrake(c);
	m_VehicleInputData.setDigitalHandbrake(c);
}

void S_Px车::f_转向(const int8 c) {
	if (c > 0) {
		m_VehicleInputData.setDigitalSteerRight(true);
	}
	else if (c < 0) {
		m_VehicleInputData.setDigitalSteerLeft(true);
	}
	else {
		m_VehicleInputData.setDigitalSteerRight(false);
		m_VehicleInputData.setDigitalSteerLeft(false);
	}
}

void S_Px车::f_加减档(const int8 c) {
	m_车辆驱动->mDriveDynData.forceGearChange((PxVehicleGearsData::Enum)c);
}


//PxVehicleTelemetryData









vec3 S_Px车::f_get速度(physx::PxRigidDynamic & obj)
{
	PxVec3 v = m_车体刚体->getLinearVelocity();
	return {v.x, v.y, v.z};
}

vec3 S_Px车::f_get角度(physx::PxRigidDynamic & obj)
{
	PxVec3 v = m_车体刚体->getAngularVelocity();
	return { v.x, v.y, v.z };
}



void S_Px车::f_setLocRot(const vec3& l, const vec3& r) {
	vec4 q = f_graph_欧拉角转四元数(r);
	PxTransform startTransform(PxVec3(l.x, l.y, l.z), PxQuat(q.x, q.y, q.z, q.w));
	m_车体刚体->setGlobalPose(startTransform);
	//m_车体形状[0]->setLocalPose(startTransform);
}

void S_Px车::f_setPos(const vec3 & loc) {
	PxTransform startTransform(PxVec3(loc.x, loc.y, loc.z), PxQuat(PxIdentity));
	m_车体刚体->setGlobalPose(startTransform);	
}

void S_Px车::f_setRot(const vec3& r) {
}

void S_Px车::f_setVel(const vec3& v) {
	m_车体刚体->setLinearVelocity({ v.x, v.y, v.z });
	m_车体刚体->setAngularVelocity({ v.x, v.y, v.z });
}
































PxErrorCallback& getSampleErrorCallback() {
	static PxDefaultErrorCallback gDefaultErrorCallback;
	return gDefaultErrorCallback;
}

PxU32 gNumVehicleAdded = 0;

#define NUM_PLAYER_CARS 1
#define NUM_NONPLAYER_4W_VEHICLES 1
#define NUM_NONPLAYER_6W_VEHICLES 0


enum
{
	LOAD_TYPE_VEHICLE = 0,
	LOAD_TYPE_LOOPTHELOOP,
	LOAD_TYPE_SKYDOME,
	MAX_NUM_LOAD_TYPES
};
static PxU32 gLoadType = MAX_NUM_LOAD_TYPES;


enum
{
	CAR_PART_FRONT_LEFT_WHEEL = 0,
	CAR_PART_FRONT_RIGHT_WHEEL,
	CAR_PART_REAR_LEFT_WHEEL,
	CAR_PART_REAR_RIGHT_WHEEL,
	CAR_PART_CHASSIS,
	CAR_PART_WINDOWS,
	NUM_CAR4W_RENDER_COMPONENTS,
	CAR_PART_EXTRA_WHEEL0 = NUM_CAR4W_RENDER_COMPONENTS,
	CAR_PART_EXTRA_WHEEL1,
	NUM_CAR6W_RENDER_COMPONENTS
};






///////////////////////////////////
//VEHICLE START PARAMETERS
///////////////////////////////////
static PxTransform gPlayerCarStartTransforms[NUM_PLAYER_CARS] = {
	PxTransform(PxVec3(-154.699753f, 9.863837f, 87.684113f), PxQuat(-0.000555f, -0.267015, 0.000155, -0.963692))
};


struct CarRenderUserData {
	PxU8	carId;
	PxU8	carPart;
	PxU8	carPartDependency;
	PxU8	pad;
};

static const CarRenderUserData gCar4WRenderUserData[NUM_CAR6W_RENDER_COMPONENTS] = {
	//wheel fl		wheel fr		wheel rl		wheel rl		chassis			windows		extra wheel0		extra wheel1		
	{0,0,255},		{0,1,255},		{0,2,255},		{0,3,255},		{0,4,255},		{0,4,4},	{255,255,255},		{255,255,255}
};
static const CarRenderUserData gCar6WRenderUserData[NUM_CAR6W_RENDER_COMPONENTS] = {
	//wheel fl		wheel fr		wheel rl		wheel rl		chassis			windows		extra wheel0		extra wheel1	
	{0,0,255},		{0,1,255},		{0,2,255},		{0,3,255},		{0,6,255},		{0,6,6},	{0,4,255},			{0,5,255}
};




#if NUM_NONPLAYER_4W_VEHICLES 
static PxTransform gVehicle4WStartTransforms[NUM_NONPLAYER_4W_VEHICLES] =
{
	//Stack of 2 cars
	PxTransform(PxVec3(4, 5.8764671f, 4.47554f), PxQuat(0.00062184106f,0.97696519f,-0.0029967001f,0.21337670f)),
	/*PxTransform(PxVec3(-78.796158f,11.7764671f,155.47554f), PxQuat(0.00062184106f,0.97696519f,-0.0029967001f,0.21337670f)),
	
	//Stack of 2 cars
	PxTransform(PxVec3(-80.391357f,9.8760214f,161.93578f), PxQuat(1.0251222e-005f, 0.98799443f, -6.0369461e-005f, 0.15448983f)),
	PxTransform(PxVec3(-80.391357f,11.7760214f,161.93578f), PxQuat(1.0251222e-005f, 0.98799443f, -6.0369461e-005f, 0.15448983f)),

	//Bookends to car stacks
	PxTransform(PxVec3(-77.945328f,9.9765568f,151.78404f), PxQuat(0.0014836629f,-0.86193967f,0.0024594457f,0.50700283f)),
	PxTransform(PxVec3(-80.395328f,9.8786600f,167.44662f), PxQuat(0.0014836629f,-0.86193967f,0.0024594457f,0.50700283f)),

	//Car in-between two ramps
	PxTransform(PxVec3(116.04498f,9.9760214f,139.02933f), PxQuat(7.5981094e-005f,-0.38262743f,-3.1461415e-005f,-0.92390275f)),*/
};
#endif


#if NUM_NONPLAYER_6W_VEHICLES
static PxTransform gVehicle6WStartTransforms[NUM_NONPLAYER_6W_VEHICLES] = {
	//6-wheeled car
	PxTransform(PxVec3(-158.09471f,9.8649321f,80.359474f), PxQuat(-0.0017525638f,-0.24773766f,0.00040674198f,-0.96882552f))
};
#endif


#define NUM_NONPLAYER_4W_TANKS 0
#if NUM_NONPLAYER_4W_TANKS 
static PxTransform gTank4WStartTransforms[NUM_NONPLAYER_4W_TANKS] = {
	//6-wheeled car
	PxTransform(PxVec3(-158.09471f,9.8649321f,80.359474f), PxQuat(-0.0017525638f,-0.24773766f,0.00040674198f,-0.96882552f))
};
#endif

#define NUM_NONPLAYER_6W_TANKS 0
#if NUM_NONPLAYER_6W_TANKS 
static PxTransform gTank6WStartTransforms[NUM_NONPLAYER_6W_TANKS] = {
	//6-wheeled car
	PxTransform(PxVec3(-158.09471f,9.8649321f,80.359474f), PxQuat(-0.0017525638f,-0.24773766f,0.00040674198f,-0.96882552f))
};
#endif




CarRenderUserData gVehicleRenderUserData[NUM_PLAYER_CARS + NUM_NONPLAYER_4W_VEHICLES + NUM_NONPLAYER_6W_VEHICLES + NUM_NONPLAYER_4W_TANKS + NUM_NONPLAYER_6W_TANKS][NUM_CAR6W_RENDER_COMPONENTS];



////////////////////////////////////////////////////////////////
//TRANSFORM APPLIED TO CHASSIS RENDER MESH VERTS 
//THAT IS REQUIRED TO PLACE AABB OF CHASSIS RENDER MESH AT ORIGIN
//AT CENTRE-POINT OF WHEELS.
////////////////////////////////////////////////////////////////
static PxVec3 gChassisMeshTransform(0, 0, 0);


////////////////////////////////////////////////////////////////
//WHEEL CENTRE OFFSETS FROM CENTRE OF CHASSIS RENDER MESH AABB
//OF 4-WHEELED VEHICLE 
////////////////////////////////////////////////////////////////
static PxVec3 gWheelCentreOffsets4[4];




////////////////////////////////////////////////////////////////
//CONVEX HULL OF RENDER MESH FOR CHASSIS AND WHEELS OF
//4-WHEELED VEHICLE
////////////////////////////////////////////////////////////////
static PxConvexMesh* gChassisConvexMesh = NULL;
static PxConvexMesh* gWheelConvexMeshes4[4] = { NULL,NULL,NULL,NULL };





////////////////////////////////////////////////////////////////
//Revolute joints and gian pendula
////////////////////////////////////////////////////////////////

#define MAX_NUM_PENDULA 4

PxTransform gPendulaBallStartTransforms[MAX_NUM_PENDULA] =
{
	PxTransform(PxVec3(151.867020 , 11.364232 , 97.350906), PxQuat(-0.000106 , -0.951955 , 0.000370 , -0.306239)) ,
	PxTransform(PxVec3(163.001953 , 11.364203 , 77.854568), PxQuat(-0.000070 , -0.971984 , 0.000323 , -0.235048)) ,
	PxTransform(PxVec3(173.971405 , 11.364145 , 45.944290), PxQuat(-0.000050 , -0.994988 , 0.000448 , -0.099990)) ,
	PxTransform(PxVec3(179.876785 , 11.364090 , 3.679581), PxQuat(-0.000024 , -1.000000 , 0.000431 , -0.000193))
};

PxF32 gPendulumBallRadius = 2.0f;
PxF32 gPendulumBallMass = 1000.0f;
PxF32 gPendulumShaftLength = 10.0f;
PxF32 gPendulumShaftWidth = 0.1f;
PxF32 gPendulumSuspensionStructureWidth = 13.0f;

PxRevoluteJoint* gRevoluteJoints[MAX_NUM_PENDULA] = { NULL,NULL,NULL,NULL };
PxF32 gRevoluteJointDriveSpeeds[MAX_NUM_PENDULA] = { 0.932f,1.0f,1.237f,0.876f };
PxF32 gRevoluteJointTimers[MAX_NUM_PENDULA] = { 0,0,0,0 };
PxU32 gNumRevoluteJoints = 0;
PxF32 gRevoluteJointMaxTheta = 0;






////////////////////////////////////////////////////////////////
//Route
////////////////////////////////////////////////////////////////

PxTransform gWayPoints[35] =
{
	PxTransform(PxVec3(-154.699753f , 9.863837f , 87.684113f), PxQuat(-0.000555f , -0.267015f , 0.000155f , -0.963692f)) ,
	PxTransform(PxVec3(-133.385757f , 9.863703f , 118.680717f), PxQuat(-0.000620f , -0.334975f , 0.000219f , -0.942227f)) ,
	PxTransform(PxVec3(-103.853020f , 9.863734f , 146.631256f), PxQuat(-0.000560f , -0.474673f , 0.000301f , -0.880162f)) ,
	PxTransform(PxVec3(-20.397881f , 9.862607f , 177.345657f), PxQuat(-0.000938f , -0.674493f , 0.000867f , -0.738281f)) ,
	PxTransform(PxVec3(14.272619f , 9.863173f , 178.745789f), PxQuat(-0.000736f , -0.723563f , 0.000740f , -0.690257f)) ,
	PxTransform(PxVec3(49.057743f , 9.862507f , 173.464539f), PxQuat(-0.000387f , -0.794072f , 0.001316f , -0.607822f)) ,
	PxTransform(PxVec3(82.226036f , 9.862642f , 159.649200f), PxQuat(-0.000670f , -0.853613f , 0.001099f , -0.520905f)) ,
	PxTransform(PxVec3(158.675018f , 9.864265f , 86.166740f), PxQuat(-0.000052f , -0.973169f , 0.000286f , -0.230092f)) ,
	PxTransform(PxVec3(165.983170f , 9.857763f , 67.031097f), PxQuat(-0.014701f , -0.979587f , 0.002133f , 0.200471f)) ,
	PxTransform(PxVec3(177.577393f , 9.864532f , 30.462427f), PxQuat(0.000022f , -0.998473f , -0.000423f , -0.055239f)) ,
	PxTransform(PxVec3(180.127686f , 9.864151f , -10.116920f), PxQuat(0.000011f , 0.999869f , 0.000295f , -0.016194f)) ,
	PxTransform(PxVec3(174.281616f , 9.863608f , -42.319435f), PxQuat(0.000168f , 0.989981f , -0.001008f , -0.141194f)) ,
	PxTransform(PxVec3(166.054413f , 9.864248f , -68.973045f), PxQuat(-0.000052f , 0.985021f , -0.000213f , -0.172433f)) ,
	PxTransform(PxVec3(154.505814f , 9.864180f , -77.992622f), PxQuat(-0.000098f , 0.754213f , -0.000129f , -0.656630f)) ,
	PxTransform(PxVec3(140.834076f , 9.863158f , -78.122841f), PxQuat(-0.000730f , 0.709598f , -0.000737f , -0.704606f)) ,
	PxTransform(PxVec3(100.152573f , 9.853898f , -78.407364f), PxQuat(0.066651f , 0.683499f , 0.070412f , -0.723484f)) ,
	PxTransform(PxVec3(68.866241f , 10.293923f , -77.979095f), PxQuat(-0.045687f , 0.703115f , -0.044258f , -0.708225f)),
	PxTransform(PxVec3(26.558704f , 10.495461f , -77.729164f), PxQuat(-0.018349f , 0.708445f , -0.018563f , -0.705283f)) ,
	PxTransform(PxVec3(-2.121686f , 9.860541f , -77.735886f), PxQuat(-0.000792f , 0.706926f , -0.000792f , -0.707287f)) ,
	PxTransform(PxVec3(-28.991186f , 9.867218f , -77.722122f), PxQuat(-0.000251f , 0.706926f , -0.000251f , -0.707287f)) ,
	PxTransform(PxVec3(-59.285870f , 9.861916f , -77.746246f), PxQuat(-0.001042f , 0.708723f , -0.001048f , -0.705485f)) ,
	PxTransform(PxVec3(-73.170433f , 9.863565f , -78.034157f), PxQuat(-0.001567f , 0.736642f , -0.001323f , -0.676280f)) ,
	PxTransform(PxVec3(-77.792152f , 9.864209f , -87.821510f), PxQuat(0.000006f , 0.999772f , -0.000294f , -0.021342f)) ,
	PxTransform(PxVec3(-78.164032f , 9.862655f , -114.313690f), PxQuat(-0.000010f , 0.999962f , -0.001280f , -0.008618f)),
	PxTransform(PxVec3(-78.567627f , 9.862757f , -137.274292f), PxQuat(-0.000010f , 0.999961f , -0.001146f , -0.008796f)) ,
	PxTransform(PxVec3(-80.392769f , 9.863695f , -149.740082f), PxQuat(-0.000149f , 0.987276f , -0.000512f , -0.159015f)) ,
	PxTransform(PxVec3(-88.452507f , 9.864114f , -152.396698f), PxQuat(-0.000355f , 0.622921f , -0.000278f , -0.782285f)) ,
	PxTransform(PxVec3(-106.042450f , 9.863844f , -144.640076f), PxQuat(-0.000485f , 0.459262f , -0.000133f , -0.888301f)) ,
	PxTransform(PxVec3(-134.893997f , 15.093562f , -114.433586f), PxQuat(0.073759f , 0.354141f , 0.027569f , -0.931871f)) ,
	PxTransform(PxVec3(-145.495453f , 9.864394f , -101.019417f), PxQuat(-0.000351f , 0.305924f , -0.000104f , -0.952056f)) ,
	PxTransform(PxVec3(-152.808212f , 9.864192f , -86.800613f), PxQuat(-0.000099f , 0.206095f , -0.000015f , -0.978532f)) ,
	PxTransform(PxVec3(-156.457855f , 9.864244f , -81.270035f), PxQuat(-0.000420f , 0.201378f , -0.000086f , -0.979514f)) ,
	PxTransform(PxVec3(-169.079376f , 10.192255f , -48.906967f), PxQuat(0.003633f , 0.179159f , 0.000892f , -0.983813f)) ,
	PxTransform(PxVec3(-151.470123f , 7.783551f , -17.838057f), PxQuat(0.029215f , -0.077987f , -0.050732f , -0.995234f)) ,
	PxTransform(PxVec3(-171.549225f , 9.864206f , 47.239426f), PxQuat(-0.000319f , -0.159609f , 0.000039f , -0.987180f))
};
PxU32 gNumWayPoints = 35;








////////////////////////////////////////////////////////////////
//VEHICLE SETUP DATA 
////////////////////////////////////////////////////////////////

PxF32 gChassisMass = 1500.0f;
PxF32 gSuspensionShimHeight = 0.125f;





bool S_Px车::f_test(S_Px物理引擎核心* core, physx::PxScene* scene, S_车体参数& 车体, vector<S_车轮参数>& 车轮s) {
	gChassisConvexMesh = 0;//(PxConvexMesh*)车体.m_车体物理体[0]->f_get几何体物理对象();
	for (uint32 i = 0; i < 4; ++i) {
		//gWheelConvexMeshes4[i] = (PxConvexMesh*)车轮s[i].m_车轮物理体->f_get几何体物理对象();

		if (!gWheelConvexMeshes4[i]) return false;
		//auto offset位置 = vec_sub(车体.m_位置, 车轮s[i].m_位置);
		auto offset位置 = vec_sub(车轮s[i].m_位置, 车体.m_位置);
		gWheelCentreOffsets4[i].x = offset位置.x;
		gWheelCentreOffsets4[i].y = offset位置.y;
		gWheelCentreOffsets4[i].z = offset位置.z;
	}



	const PxF32 restitutions[MAX_NUM_SURFACE_TYPES] = { 0.2f, 0.2f, 0.2f, 0.2f };
	const PxF32 staticFrictions[MAX_NUM_SURFACE_TYPES] = { 0.5f, 0.5f, 0.5f, 0.5f };
	const PxF32 dynamicFrictions[MAX_NUM_SURFACE_TYPES] = { 0.5f, 0.5f, 0.5f, 0.5f };

	for (PxU32 i = 0;i < MAX_NUM_SURFACE_TYPES;i++)
	{
		//Create a new material.
		mStandardMaterials[i] = core->m_Physics->createMaterial(staticFrictions[i], dynamicFrictions[i], restitutions[i]);
		if (!mStandardMaterials[i])
		{
			getSampleErrorCallback().reportError(PxErrorCode::eINTERNAL_ERROR, "createMaterial failed", __FILE__, __LINE__);
		}

		//Set up the drivable surface type that will be used for the new material.
		mVehicleDrivableSurfaceTypes[i].mType = i;
	}

	mChassisMaterialDrivable = core->m_Physics->createMaterial(0.0f, 0.0f, 0.0f);
	if (!mChassisMaterialDrivable)
	{
		getSampleErrorCallback().reportError(PxErrorCode::eINTERNAL_ERROR, "createMaterial failed", __FILE__, __LINE__);
	}

	mChassisMaterialNonDrivable = core->m_Physics->createMaterial(1.0f, 1.0f, 0.0f);
	if (!mChassisMaterialNonDrivable)
	{
		getSampleErrorCallback().reportError(PxErrorCode::eINTERNAL_ERROR, "createMaterial failed", __FILE__, __LINE__);
	}



















	bool hasFocusVehicle = false;
	//Make sure that we set the foundation before doing anything.
	mVehicleManager.init(*core->m_Physics, (const PxMaterial**)mStandardMaterials, mVehicleDrivableSurfaceTypes);

	//Not added any vehicles yet.
	gNumVehicleAdded = 0;

	//Load the vehicle model (this will add the render actors for the chassis, 4 wheels, and windows).
	gLoadType = LOAD_TYPE_VEHICLE;
	//importRAWFile("car2.raw", 1.0f);

	//The extra wheels of an 8-wheeled vehicle are instanced from the 4 wheels of the 4-wheeled car.
	//gRenderMeshActors[CAR_PART_EXTRA_WHEEL0] = gRenderMeshActors[CAR_PART_FRONT_LEFT_WHEEL];
	//gRenderMeshActors[CAR_PART_EXTRA_WHEEL1] = gRenderMeshActors[CAR_PART_FRONT_RIGHT_WHEEL];

	//Clear the array of render actors before adding the actors for each vehicle.
	//for (PxU32 i = 0;i < mRenderActors.size();i++)
	//{
	//	RenderBaseActor* renderActor = mRenderActors[i];
	//	renderActor->setRendering(false);
	//}
	//mPlayerVehicleType = ePLAYER_VEHICLE_TYPE_VEHICLE4W;

	//Load the player car.
	switch (mPlayerVehicleType)
	{
	case ePLAYER_VEHICLE_TYPE_VEHICLE4W:
	case ePLAYER_VEHICLE_TYPE_TANK4W:
	{
		for (PxU32 i = 0; i < NUM_CAR4W_RENDER_COMPONENTS; i++) {
			gVehicleRenderUserData[gNumVehicleAdded][i] = gCar4WRenderUserData[i];
			gVehicleRenderUserData[gNumVehicleAdded][i].carId = PxU8(gNumVehicleAdded);
			//RenderMeshActor* clone = SAMPLE_NEW(RenderMeshActor)(*gRenderMeshActors[i]);
			//clone->setRendering(true);
			//clone->mUserData = &gVehicleRenderUserData[gNumVehicleAdded][i];
			//clone->setEnableCameraCull(true);
			//mVehicleGraphics.push_back(clone);
			//mRenderActors.push_back(clone);
		}

		mPlayerVehicle = 0;
		if (!hasFocusVehicle)
		{
			if (ePLAYER_VEHICLE_TYPE_VEHICLE4W == mPlayerVehicleType) {
				mVehicleManager.create4WVehicle(*scene, *core->m_Physics, *core->m_Cooking, *mChassisMaterialDrivable, gChassisMass, gWheelCentreOffsets4, gChassisConvexMesh, gWheelConvexMeshes4, gPlayerCarStartTransforms[0], true);
			}
			else {
				mVehicleManager.create4WTank(*scene, *core->m_Physics, *core->m_Cooking, *mChassisMaterialDrivable, gChassisMass, gWheelCentreOffsets4, gChassisConvexMesh, gWheelConvexMeshes4, gPlayerCarStartTransforms[0], true, mTankDriveModel);
			}
		}

		gNumVehicleAdded++;
	}
	break;

	case ePLAYER_VEHICLE_TYPE_VEHICLE6W:
	case ePLAYER_VEHICLE_TYPE_TANK6W:
	{
		for (PxU32 i = 0;i < NUM_CAR4W_RENDER_COMPONENTS;i++)
		{
			gVehicleRenderUserData[gNumVehicleAdded][i] = gCar6WRenderUserData[i];
			gVehicleRenderUserData[gNumVehicleAdded][i].carId = PxU8(gNumVehicleAdded);

			//RenderMeshActor* clone = SAMPLE_NEW(RenderMeshActor)(*gRenderMeshActors[i]);
			//clone->setRendering(true);
			//clone->mUserData = &gVehicleRenderUserData[gNumVehicleAdded][i];
			//clone->setEnableCameraCull(true);
			//mVehicleGraphics.push_back(clone);
			//mRenderActors.push_back(clone);
		}

		gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL0] = gCar6WRenderUserData[CAR_PART_EXTRA_WHEEL0];
		gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL1] = gCar6WRenderUserData[CAR_PART_EXTRA_WHEEL1];
		gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL0].carId = PxU8(gNumVehicleAdded);
		gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL1].carId = PxU8(gNumVehicleAdded);

		//Add the extra wheels.
		//RenderMeshActor* clone;
		//clone = SAMPLE_NEW(RenderMeshActor)(*gRenderMeshActors[CAR_PART_EXTRA_WHEEL0]);
		//clone->setRendering(true);
		//clone->mUserData = &gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL0];
		//clone->setEnableCameraCull(true);
		//mVehicleGraphics.push_back(clone);
		//mRenderActors.push_back(clone);
		//clone = SAMPLE_NEW(RenderMeshActor)(*gRenderMeshActors[CAR_PART_EXTRA_WHEEL1]);
		//clone->setRendering(true);
		//clone->mUserData = &gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL1];
		//clone->setEnableCameraCull(true);
		//mVehicleGraphics.push_back(clone);
		//mRenderActors.push_back(clone);

		mPlayerVehicle = 0;
		if (!hasFocusVehicle) {
			if (ePLAYER_VEHICLE_TYPE_VEHICLE6W == mPlayerVehicleType) {
				mVehicleManager.create6WVehicle(*scene, *core->m_Physics, *core->m_Cooking, *mChassisMaterialDrivable, gChassisMass, gWheelCentreOffsets4, gChassisConvexMesh, gWheelConvexMeshes4, gPlayerCarStartTransforms[0], true);
			}
			else {
				mVehicleManager.create6WTank(*scene, *core->m_Physics, *core->m_Cooking, *mChassisMaterialDrivable, gChassisMass, gWheelCentreOffsets4, gChassisConvexMesh, gWheelConvexMeshes4, gPlayerCarStartTransforms[0], true, mTankDriveModel);
			}
		}
		gNumVehicleAdded++;
	}
	break;

	default:
		PX_ASSERT(false);
		break;
	}

#if NUM_NONPLAYER_4W_VEHICLES
	for (PxU32 i = 0;i < NUM_NONPLAYER_4W_VEHICLES;i++)
	{
		//Clone the meshes from the instanced meshes.
		for (PxU32 j = 0; j < NUM_CAR4W_RENDER_COMPONENTS; j++) {
			gVehicleRenderUserData[gNumVehicleAdded][j] = gCar4WRenderUserData[j];
			gVehicleRenderUserData[gNumVehicleAdded][j].carId = PxU8(gNumVehicleAdded);
			//RenderMeshActor* clone = SAMPLE_NEW(RenderMeshActor)(*gRenderMeshActors[j]);
			//clone->setRendering(true);
			//clone->mUserData = &gVehicleRenderUserData[gNumVehicleAdded][j];
			//clone->setEnableCameraCull(true);
			//mVehicleGraphics.push_back(clone);
			//mRenderActors.push_back(clone);
		}

		//Add the next vehicle.
		mVehicleManager.create4WVehicle(*scene, *core->m_Physics, *core->m_Cooking, *mChassisMaterialNonDrivable, gChassisMass, gWheelCentreOffsets4, gChassisConvexMesh, gWheelConvexMeshes4, gVehicle4WStartTransforms[i], true);

		gNumVehicleAdded++;
	}
#endif

#if NUM_NONPLAYER_6W_VEHICLES
	for (PxU32 i = 0;i < NUM_NONPLAYER_6W_VEHICLES;i++) {
		//Clone the meshes from the instanced meshes.
		for (PxU32 j = 0;j < NUM_CAR4W_RENDER_COMPONENTS;j++) {
			gVehicleRenderUserData[gNumVehicleAdded][j] = gCar6WRenderUserData[j];
			gVehicleRenderUserData[gNumVehicleAdded][j].carId = PxU8(gNumVehicleAdded);

			//RenderMeshActor* clone = SAMPLE_NEW(RenderMeshActor)(*gRenderMeshActors[j]);
			//clone->setRendering(true);
			//clone->mUserData = &gVehicleRenderUserData[gNumVehicleAdded][j];
			//clone->setEnableCameraCull(true);
			//mVehicleGraphics.push_back(clone);
			//mRenderActors.push_back(clone);
		}
		//Add the extra wheels.
		gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL0] = gCar6WRenderUserData[CAR_PART_EXTRA_WHEEL0];
		gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL1] = gCar6WRenderUserData[CAR_PART_EXTRA_WHEEL1];
		gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL0].carId = PxU8(gNumVehicleAdded);
		gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL1].carId = PxU8(gNumVehicleAdded);

		//RenderMeshActor* clone;
		//clone = SAMPLE_NEW(RenderMeshActor)(*gRenderMeshActors[CAR_PART_EXTRA_WHEEL0]);
		//clone->setRendering(true);
		//clone->mUserData = &gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL0];
		//clone->setEnableCameraCull(true);
		//mVehicleGraphics.push_back(clone);
		//mRenderActors.push_back(clone);
		//clone = SAMPLE_NEW(RenderMeshActor)(*gRenderMeshActors[CAR_PART_EXTRA_WHEEL1]);
		//clone->setRendering(true);
		//clone->mUserData = &gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL1];
		//clone->setEnableCameraCull(true);
		//mVehicleGraphics.push_back(clone);
		//mRenderActors.push_back(clone);

		//Add the next vehicle.
		mVehicleManager.create6WVehicle(*scene, *core->m_Physics, *core->m_Cooking, *mChassisMaterialNonDrivable, gChassisMass, gWheelCentreOffsets4, gChassisConvexMesh, gWheelConvexMeshes4, gVehicle6WStartTransforms[i], true);
		gNumVehicleAdded++;
	}
#endif

#if NUM_NONPLAYER_4W_TANKS 
	for (PxU32 i = 0;i < NUM_NONPLAYER_4W_TANKS;i++)
	{
		//Clone the meshes from the instanced meshes.
		for (PxU32 j = 0;j < NUM_CAR4W_RENDER_COMPONENTS;j++)
		{
			gVehicleRenderUserData[gNumVehicleAdded][j] = gCar4WRenderUserData[j];
			gVehicleRenderUserData[gNumVehicleAdded][j].carId = PxU8(gNumVehicleAdded);

			RenderMeshActor* clone = SAMPLE_NEW(RenderMeshActor)(*gRenderMeshActors[j]);
			clone->setRendering(true);
			clone->mUserData = &gVehicleRenderUserData[gNumVehicleAdded][j];
			clone->setEnableCameraCull(true);

			mVehicleGraphics.push_back(clone);
			mRenderActors.push_back(clone);
		}

		mPlayerVehicle = 0;
		//Add the next vehicle.
		mVehicleManager.create4WTank(getActiveScene(), getPhysics(), getCooking(), *mChassisMaterial, gChassisMass, gWheelCentreOffsets4, gChassisConvexMesh, gWheelConvexMeshes4, gTank4WStartTransforms[i], true, PxVehicleDriveTank::eDRIVE_MODEL_SPECIAL);

		gNumVehicleAdded++;
	}
#endif

#if NUM_NONPLAYER_6W_TANKS 
	for (PxU32 i = 0;i < NUM_NONPLAYER_6W_TANKS;i++)
	{
		//Clone the meshes from the instanced meshes.
		for (PxU32 j = 0;j < NUM_CAR4W_RENDER_COMPONENTS;j++)
		{
			gVehicleRenderUserData[gNumVehicleAdded][j] = gTank6WRenderUserData[j];
			gVehicleRenderUserData[gNumVehicleAdded][j].carId = PxU8(gNumVehicleAdded);

			RenderMeshActor* clone = SAMPLE_NEW(RenderMeshActor)(*gRenderMeshActors[j]);
			clone->setRendering(true);
			clone->mUserData = &gVehicleRenderUserData[gNumVehicleAdded][j];
			clone->setEnableCameraCull(true);

			mVehicleGraphics.push_back(clone);
			mRenderActors.push_back(clone);
		}

		//Add the extra wheels.

		gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL0] = gTank6WRenderUserData[CAR_PART_EXTRA_WHEEL0];
		gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL1] = gTank6WRenderUserData[CAR_PART_EXTRA_WHEEL1];
		gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL0].carId = PxU8(gNumVehicleAdded);
		gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL1].carId = PxU8(gNumVehicleAdded);

		RenderMeshActor* clone;

		clone = SAMPLE_NEW(RenderMeshActor)(*gRenderMeshActors[CAR_PART_EXTRA_WHEEL0]);
		clone->setRendering(true);
		clone->mUserData = &gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL0];
		clone->setEnableCameraCull(true);
		mVehicleGraphics.push_back(clone);
		mRenderActors.push_back(clone);

		clone = SAMPLE_NEW(RenderMeshActor)(*gRenderMeshActors[CAR_PART_EXTRA_WHEEL1]);
		clone->setRendering(true);
		clone->mUserData = &gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL1];
		clone->setEnableCameraCull(true);
		mVehicleGraphics.push_back(clone);
		mRenderActors.push_back(clone);

		//Add the next vehicle.
		mVehicleManager.create6WTank(getActiveScene(), getPhysics(), getCooking(), *mChassisMaterial, gChassisMass, gWheelCentreOffsets4, gChassisConvexMesh, gWheelConvexMeshes4, gTank6WStartTransforms[i], true);

		gNumVehicleAdded++;
	}
#endif





	return true;
}











